// ignore_for_file: depend_on_referenced_packages

import 'dart:ffi';

import 'package:flutter_2b_client/apis/MarketDeliveryOrderApi.dart';
import 'package:flutter_2b_client/json/LocalDateConverter.dart';
import 'package:flutter_2b_client/json/LocalDateTimeConverter.dart';
import 'package:flutter_2b_client/model/IntIdAndName.dart';
import 'package:flutter_2b_client/utils/Page.dart';
import 'package:flutter_2b_client/utils/local_datetime.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:retrofit/dio.dart';
import 'package:retrofit/http.dart';
import 'package:dio/dio.dart';

import '../model/NullableLocalDateRange.dart';
import 'Initial.dart';

part 'MarketCheckInventoryRecordApi.g.dart';

part 'MarketCheckInventoryRecordApi.freezed.dart';

@RestApi()
abstract class MarketCheckInventoryRecordApi {
  factory MarketCheckInventoryRecordApi(Dio dio, {String baseUrl}) =
      _MarketCheckInventoryRecordApi;

  @GET("markets/checkInventoryRecords")
  Future<Page<QueryMarketCheckInventoryRecordResponse>>
      _queryMarketCheckInventoryRecords(
          @Queries() Map<String, dynamic> queries);

  @GET("markets/checkInventoryRecords/employees?projection=summary")
  Future<List<IntIdAndName>> getAllMarketCheckInventoryRecordCreatedEmployees();

  @GET("markets/createdDateRanges")
  Future<NullableLocalDateRange>
      getAllMarketCheckInventoryRecordCreatedDateRange();

  @POST("markets/checkInventoryRecords")
  Future<QueryMarketCheckInventoryRecordResponse>
      createMarketCheckInventoryRecord(
          @Body() CreateMarketCheckInventoryRecordRequest request);

  @GET("markets/checkInventoryRecords/{id}")
  Future<MarketCheckInventoryRecordDetail> getMarketCheckInventoryRecordDetail(
      @Path("id") int id);

  @GET("markets/checkInventoryRecords/{id}/items")
  Future<Page<MarketCheckInventoryRecordItemSummary>>
      _queryMarketCheckInventoryRecordItems(
          @Path() int id, @Queries() Map<String, dynamic> queries);

  @PATCH("markets/checkInventoryRecords/{id}/submit")
  Future<void> submitMarketCheckInventoryRecord(@Path() int id);

  @POST("markets/checkInventoryRecords/{id}/items/goods/{goodsId}")
  Future<MarketCheckInventoryRecordItemSummary> addGoodsByGoodsId(
      @Path() int id, @Path("goodsId") int goodsId);

  @POST("markets/checkInventoryRecords/{id}/items/barcodes/{barcode}")
  Future<MarketCheckInventoryRecordItemSummary> addGoodsByGoodsBarcode(
      @Path() int id, @Path("barcode") String barcode);

  @DELETE("markets/checkInventoryRecords/{id}/items/{goodsId}")
  Future<void> deleteCheckInventoryItem(
      @Path() int id, @Path("goodsId") int goodsId);

  @PATCH("markets/checkInventoryRecords/{id}/items/{goodsId}/amount")
  Future<void> updateItemAmount(@Path() int id, @Path() int goodsId,
      @Body() UpdateItemAmountRequest updateItemAmountRequest);

  @GET("markets/checkInventoryRecords/{id}/items/barcodes/{barcode}/exists")
  Future<bool> exists(@Path() int id, @Path() String barcode);

  @DioResponseType(ResponseType.bytes)
  @GET("markets/checkInventoryRecords/{id}/excel")
  Future<List<int>> exportToExcel(@Path() int id,@Query("fields") List<String>? fields);

  @DELETE("markets/checkInventoryRecords/{id}")
  Future<void> deleteCheckInventory(@Path() int id);
}

extension MarketCheckInventoryRecordApiExtension
    on MarketCheckInventoryRecordApi {
  Future<Page<QueryMarketCheckInventoryRecordResponse>>
      queryMarketCheckInventoryRecords(
          QueryMarketCheckInventoryRecordRequest request, Pageable pageable) {
    return _queryMarketCheckInventoryRecords(
        {...pageable.toRequestParamsMap(), ...request.toJson()});
  }

  Future<Page<MarketCheckInventoryRecordItemSummary>>
      queryMarketCheckInventoryRecordItems(int id, Pageable pageable) {
    return _queryMarketCheckInventoryRecordItems(
        id, pageable.toRequestParamsMap());
  }
}

@freezed
class MarketCheckInventoryRecordItemSummary
    with _$MarketCheckInventoryRecordItemSummary {
  const factory MarketCheckInventoryRecordItemSummary({
    required int goodsId,
    required String name,
    required String barcode,
    required int amount,
    required int inStore,
    required String? boxSpecification,
  }) = _MarketCheckInventoryRecordItemSummary;

  const MarketCheckInventoryRecordItemSummary._();

  factory MarketCheckInventoryRecordItemSummary.fromJson(
          Map<String, dynamic> json) =>
      _$MarketCheckInventoryRecordItemSummaryFromJson(json);
}

@freezed
class MarketCheckInventoryRecordDetail with _$MarketCheckInventoryRecordDetail {
  const factory MarketCheckInventoryRecordDetail({
    required int id,
    @LocalDateTimeConverter() required LocalDateTime createdDateTime,
    required String name,
    required IntIdAndName createdBy,
    @LocalDateTimeConverter() required LocalDateTime? submittedDateTime,
    required IntIdAndName market,
  }) = _MarketCheckInventoryRecordDetail;

  const MarketCheckInventoryRecordDetail._();

  factory MarketCheckInventoryRecordDetail.fromJson(
          Map<String, dynamic> json) =>
      _$MarketCheckInventoryRecordDetailFromJson(json);
}

@freezed
class CreateMarketCheckInventoryRecordRequest
    with _$CreateMarketCheckInventoryRecordRequest {
  const factory CreateMarketCheckInventoryRecordRequest({
    String? name,
    required int marketId,
  }) = _CreateMarketCheckInventoryRecordRequest;

  const CreateMarketCheckInventoryRecordRequest._();

  factory CreateMarketCheckInventoryRecordRequest.fromJson(
          Map<String, dynamic> json) =>
      _$CreateMarketCheckInventoryRecordRequestFromJson(json);
}

@freezed
class QueryMarketCheckInventoryRecordResponse
    with _$QueryMarketCheckInventoryRecordResponse {
  const factory QueryMarketCheckInventoryRecordResponse({
    required int id,
    required IntIdAndName createdBy,
    @LocalDateTimeConverter() required LocalDateTime createdDateTime,
    required int goodsKindAmount,
    required String name,
    @LocalDateTimeConverter() LocalDateTime? submittedDateTime,
    required IntIdAndName market,
  }) = _QueryMarketCheckInventoryRecordResponse;

  const QueryMarketCheckInventoryRecordResponse._();

  factory QueryMarketCheckInventoryRecordResponse.fromJson(
          Map<String, dynamic> json) =>
      _$QueryMarketCheckInventoryRecordResponseFromJson(json);
}

@freezed
class QueryMarketCheckInventoryRecordRequest
    with _$QueryMarketCheckInventoryRecordRequest {
  const factory QueryMarketCheckInventoryRecordRequest({
    @LocalDateConverter() LocalDate? startDate,
    @LocalDateConverter() LocalDate? endDate,
    @Default([]) List<int> employeeIds,
    bool? submitted,
    @Default([]) List<int> marketIds,
  }) = _QueryMarketCheckInventoryRecordRequest;

  const QueryMarketCheckInventoryRecordRequest._();

  factory QueryMarketCheckInventoryRecordRequest.fromJson(
          Map<String, dynamic> json) =>
      _$QueryMarketCheckInventoryRecordRequestFromJson(json);

  bool hasAnyFilter() {
    return startDate != null ||
        endDate != null ||
        employeeIds.isNotEmpty ||
        submitted != null;
  }
}

MarketCheckInventoryRecordApi marketCheckInventoryRecordApi =
    MarketCheckInventoryRecordApi(dio, baseUrl: baseUrl);
